#include "NetworkManager.h"
#include <QHostAddress>
#include <iostream>

NetworkManager::NetworkManager(QObject* parent)
    : QObject(parent)
    , m_socket(new QTcpSocket(this))
    , m_packetSize(0)
    , m_connected(false)
{
    connect(m_socket, &QTcpSocket::connected, this, &NetworkManager::onConnected);
    connect(m_socket, &QTcpSocket::disconnected, this, &NetworkManager::onDisconnected);
    connect(m_socket, &QTcpSocket::readyRead, this, &NetworkManager::onReadyRead);
    connect(m_socket, &QTcpSocket::errorOccurred, this, &NetworkManager::onErrorOccurred);
}

NetworkManager::~NetworkManager()
{
}

void NetworkManager::connectToServer(const QString& host, quint16 port)
{
    m_socket->connectToHost(host, port);
}

void NetworkManager::disconnectFromServer()
{
    m_socket->disconnectFromHost();
}

void NetworkManager::registerAccount(const QString& username, const QString& password)
{
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream << QString("account") << username << QString("password") << password;
    sendPacket(1, data); // 类型1：注册
}

void NetworkManager::login(const QString& username, const QString& password)
{
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream << QString("account") << username << QString("password") << password;
    sendPacket(2, data); // 类型2：登录
}

void NetworkManager::sendChatMessage(const QString& target, const QString& message)
{
    QString formattedMessage = QString("user_name_start%1user_name_end%2")
        .arg(target, message);
    sendPacket(3, formattedMessage.toUtf8()); // 类型3：聊天消息
}

void NetworkManager::sendFile(const QString& target, const QString& filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        return;
    }

    QString fileName = QFileInfo(filePath).fileName();
    QByteArray fileData = file.readAll();
    file.close();

    // 发送文件信息
    QString fileInfo = QString("file_name_start:%1:file_name_end").arg(fileName);
    QByteArray data = fileInfo.toUtf8() + fileData;
    sendPacket(4, data); // 类型4：发送文件
}

void NetworkManager::requestFile(const QString& fileName)
{
    sendPacket(5, fileName.toUtf8()); // 类型5：请求文件
}

void NetworkManager::addFriend(const QString& friendName)
{
    sendPacket(6, friendName.toUtf8()); // 类型6：添加好友
}

void NetworkManager::respondFriendRequest(const QString& friendName, bool accept)
{
    sendPacket(7, friendName.toUtf8()); // 类型7：处理好友申请
}

void NetworkManager::sendPacket(uint32_t type, const QByteArray& data)
{
    if (!m_connected) return;

    QByteArray packet;
    QDataStream stream(&packet, QIODevice::WriteOnly);

    // 设置为大端序
    stream.setByteOrder(QDataStream::BigEndian);

    // 协议格式：[长度][类型][数据]
    size_t totalSize = sizeof(uint32_t) + data.size();
    stream << totalSize;
    stream << type;
    stream.writeRawData(data.constData(), data.size());

    int sentBytes = m_socket->write(packet);
   
}


void NetworkManager::onReadyRead()
{
    while (m_socket->bytesAvailable() > 0) {
        if (m_packetSize == 0) {
            // 读取数据包长度
            if (m_socket->bytesAvailable() < sizeof(quint32)) return;

            QDataStream stream(m_socket);
            stream >> m_packetSize;

            if (m_packetSize > 1024 * 1024) { // 限制1MB
                m_packetSize = 0;
                return;
            }
        }

        // 检查是否收到完整数据包
        if (m_socket->bytesAvailable() < m_packetSize) return;

        // 读取类型和数据
        QDataStream stream(m_socket);
        quint32 type;
        stream >> type;

        QByteArray data(m_packetSize - sizeof(quint32), 0);
        stream.readRawData(data.data(), data.size());

        processPacket(type, data);
        m_packetSize = 0;
    }
}

void NetworkManager::processPacket(uint32_t type, const QByteArray& data)
{
    switch (type) {
    case 1: // 注册响应
        handleRegisterResponse(data);
        break;
    case 2: // 登录响应
        handleLoginResponse(data);
        break;
    case 3: // 聊天消息
        handleChatMessage(data);
        break;
    case 4: // 文件数据
        handleFileData(data);
        break;
    case 5: // 文件请求响应
        break;
    case 6: // 好友申请
        handleFriendRequest(data);
        break;
    case 7: // 好友申请结果
        emit friendRequestResult(true, QString::fromUtf8(data));
        break;
    }
}

void NetworkManager::handleLoginResponse(const QByteArray& data)
{
    QString message = QString::fromUtf8(data);
    bool success = message.contains("sussced");
    emit loginResult(success, message);
}

void NetworkManager::handleRegisterResponse(const QByteArray& data)
{
    QString message = QString::fromUtf8(data);
    bool success = message.contains("sussced");
    emit registerResult(success, message);
}

void NetworkManager::handleChatMessage(const QByteArray& data)
{
    QString message = QString::fromUtf8(data);
    // 解析消息格式："user_name_start[用户名]user_name_end[消息内容]"
    int startPos = message.indexOf("user_name_start") + 15;
    int endPos = message.indexOf("user_name_end");

    if (startPos >= 15 && endPos > startPos) {
        QString from = message.mid(startPos, endPos - startPos);
        QString content = message.mid(endPos + 13);
        emit chatMessageReceived(from, content);
    }
}

void NetworkManager::handleFileData(const QByteArray& data)
{
    QString dataStr = QString::fromUtf8(data);
    if (dataStr.startsWith("file_sent_sucess")) {
        QString fileName = dataStr.mid(16);
        emit fileReceived(fileName, QByteArray());
    }
    else {
        // 处理文件内容
        emit fileReceived("unknown", data);
    }
}

void NetworkManager::handleFriendRequest(const QByteArray& data)
{
    QString friendName = QString::fromUtf8(data);
    emit friendRequestReceived(friendName);
}

// 其他方法实现...
void NetworkManager::onConnected()
{
    m_connected = true;
    emit connected();
}

void NetworkManager::onDisconnected()
{
    m_connected = false;
    emit disconnected();
}

void NetworkManager::onErrorOccurred(QAbstractSocket::SocketError error)
{
    m_connected = false;
    emit connectionError(m_socket->errorString());
}

bool NetworkManager::isConnected() const
{
    return m_connected;
}